package com.group9.handinhand.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.group9.handinhand.dao.ActivityDao;
import com.group9.handinhand.dao.CommunityDao;
import com.group9.handinhand.dao.OfferDao;
import com.group9.handinhand.dao.UserDao;
import com.group9.handinhand.dao.model.Community;
import com.group9.handinhand.dao.model.Event;
import com.group9.handinhand.dao.model.Goods;
import com.group9.handinhand.dao.model.Offer;
import com.group9.handinhand.dao.model.OfferPost;
import com.group9.handinhand.dao.model.OfferResponse;
import com.group9.handinhand.dao.model.Services;
import com.group9.handinhand.dao.model.Skill;
import com.group9.handinhand.dao.model.User;
import com.group9.handinhand.service.so.ActivityEnums.ActivityType;
import com.group9.handinhand.service.so.CommunitySO;
import com.group9.handinhand.service.so.EventSO;
import com.group9.handinhand.service.so.OfferPostSO;
import com.group9.handinhand.service.so.OfferResponseSO;
import com.group9.handinhand.service.so.OfferSO;
import com.group9.handinhand.service.so.SkillSO;
import com.group9.handinhand.service.so.UserSO;
import com.group9.handinhand.service.so.UserTagSO;

@Transactional
@Service("offerService")
public class OfferServiceImpl implements OfferService {
	
	@Autowired
	ActivityDao activityDao;
	
	@Autowired
	OfferDao offerDao;
	
	@Autowired
	CommunityDao communityDao;
	
	@Autowired
	UserDao userDao;
	/**
	 * Saves the offer with offer user and community id
	 * @param so
	 * @param user
	 * @param communityId
	 */
	@Override
	public OfferSO saveOffer(OfferSO so, UserSO user, Long communityId) {
		
		Goods goods = null;
		Services service = null;
		
		if(so.getGoods() != null) {
			goods = activityDao.saveGoods(so.getGoods().convertToModelObject());
		}
		if(so.getService() != null) {
			SkillSO skillSO = so.getService().getRequiredSkill();
//			aynı isimle skilleri kaydetmesin
			Skill skill = activityDao.saveSkill(skillSO.convertToModelObject());
			service = so.getService().convertToModelObject();
			service.setRequiredSkill(skill);
			service = activityDao.saveService(service);
		}
		
		Community community = communityDao.findCommunityById(communityId);
		CommunitySO communitySO = community.convertToServiceObject();
		so.getModerators().addAll(communitySO.getModerators());
		
		boolean userModerator = false;
		for (UserSO moderator : communitySO.getModerators()) {
			 if(moderator.equals(user)) {
				 userModerator = true;
			 }
		}
		if(!userModerator)
			so.getModerators().add(user);			
		
		Offer model = so.convertToModelObject();
		
		model.setCommunity(community);		
		
		model.setCreator(userDao.findUserById(user.getId()));
		model.setGoods(goods);
		model.setService(service);
		
		model = offerDao.saveOffer(model);
		if(model != null)
			return model.convertToServiceObject();
		return null;
	}
	/**
	 * Gets the offer with id
	 * @param offerId
	 * return offer service object
	 */
	@Override
	public OfferSO getOfferById(Long offerId) {
		Offer model = offerDao.findOfferById(offerId);
		if(model != null)
			return model.convertToServiceObject();
		return null;
	}
	
	/**
	 * Gets the offer with tag
	 * @param tag
	 * @return the list of offers
	 */
	
	@Override
	public List<OfferSO> getOffersByTag(UserTagSO tag) {
		List<Offer> modelList = offerDao.findOffersByTag(tag);
		List<OfferSO> soList = new ArrayList<OfferSO>();
		for (Offer model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	/**
	 * Gets the offer with tag name.
	 * @param name of the tag
	 * @return list of offers
	 */
	@Override
	public List<OfferSO> getOffersByTagName(String keyword) {
		List<Offer> modelList = offerDao.findOffersByTagName(keyword);
		List<OfferSO> soList = new ArrayList<OfferSO>();
		for (Offer model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	/**
	 * Gets offer with name
	 * @param name of the offer
	 * @return the list of offers
	 * 
	 */
	@Override
	public List<OfferSO> getOffersByName(String keyword) {
		List<Offer> modelList = offerDao.findOffersByName(keyword);
		List<OfferSO> soList = new ArrayList<OfferSO>();
		for (Offer model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}

	/**
	 * Gets  offers that are responded by the user.
	 * @param user
	 * @return the list of offer
	 */
	@Override
	public List<OfferSO> getRespondedOffersByUser(UserSO user) {
		List<Offer> modelList = offerDao.findRespondedOffersByUser(user.convertToModelObject());
		List<OfferSO> soList = new ArrayList<OfferSO>();
		for (Offer model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	
	@Override
	public List<OfferSO> getModeratedOffersByUser(UserSO user) {
		List<Offer> modelList = offerDao.findModeratedOffersByUser(user.convertToModelObject());
		List<OfferSO> soList = new ArrayList<OfferSO>();
		for (Offer model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	/**
	 * Saves the offers post with offer id, user id and post
	 * @param offerId
	 * @param userId
	 * @param post
	 * 
	 */
	@Override
	public OfferPostSO saveOfferPost(Long offerId,Long userId, String post) {
		Offer offer = offerDao.findOfferById(offerId);
		User user = userDao.findUserById(userId);
		OfferPost offerPost = new OfferPost();
		offerPost.setOffer(offer);
		offerPost.setContext(post);
		offerPost.setUser(user);
		
		OfferPost model = offerDao.saveOfferPost(offerPost);
		
		if(model != null) {
			return model.convertToServiceObject();
		}
		return null;
	}
	
	@Override
	public OfferResponseSO saveOfferResponse(OfferSO offer, Long userId, int goodsAmount) {
		OfferResponse offerResponse = new OfferResponse();
		offerResponse.setOffer(offer.convertToModelObject());
		offerResponse.setUser(userDao.findUserById(userId));
		offerResponse.setRespondAmount(goodsAmount);
		OfferResponse model = offerDao.saveOfferResponse(offerResponse);
		if(model != null){
			addToRespondedAmountOfOffer(offer,goodsAmount);
			return model.convertToServiceObject();
		}
		return null;
	}

	private void addToRespondedAmountOfOffer(OfferSO offer,int amount) {
		Offer model = offerDao.findOfferById(offer.getId());
		if(offer.getActivityType() == ActivityType.GOODS){
			Goods goods = model.getGoods();
			goods.setRespondedAmount(goods.getRespondedAmount() + amount);
			activityDao.updateGoods(goods);
		}
		else if(offer.getActivityType() == ActivityType.SERVICES){
			Services services = model.getService();
			services.setRespondedAmount(services.getRespondedAmount() + amount);
			activityDao.updateServices(services);
		}
	}

	@Override
	public ArrayList<OfferResponseSO> getRequestResponsesByUserIdAndOfferId(Long userId, Long offerId) {
		ArrayList<OfferResponse> modelList = (ArrayList<OfferResponse>) offerDao.findRequestResponsesByUserIdAndOfferId(userId,offerId);
		ArrayList<OfferResponseSO> soList = new ArrayList<OfferResponseSO>();
		for (OfferResponse model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}

	@Override
	public List<UserSO> getModeratorsByOfferId(Long offerId) {
		List<User> modelList = offerDao.findModeratorsByOfferId(offerId);
		List<UserSO> soList = new ArrayList<UserSO>();
		for (User model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	/**
	 * Updates the offer.
	 */
	@Override
	public void updateOffer(OfferSO offer) {
		
		Goods goods = null;
		Services service = null;
		
		if(offer.getGoods() != null) {
			goods = activityDao.findGoodByOfferId(offer.getId());
			if(goods == null){
				goods = activityDao.saveGoods(offer.getGoods().convertToModelObject());
			}else{
				offer.getGoods().setId(goods.getId());
				activityDao.mergeGoods(offer.getGoods().convertToModelObject());
			}
			
		}
		if(offer.getService() != null) {
			Services findedService = activityDao.findServiceByOfferId(offer.getId());
			SkillSO skillSO = offer.getService().getRequiredSkill();
			if(findedService == null){
				
				Skill skill = activityDao.saveSkill(skillSO.convertToModelObject());
				service = offer.getService().convertToModelObject();
				service.setRequiredSkill(skill);
				service = activityDao.saveService(service);
			}else{
				
				offer.getService().setId(findedService.getId());
				skillSO.setId(activityDao.findSkillByServiceId(offer.getService().getId()).getId());
				Skill skill = skillSO.convertToModelObject();
				activityDao.mergeSkill(skill);
				service = offer.getService().convertToModelObject();
				service.setRequiredSkill(skill);
				activityDao.mergeServices(service);
			}
			
		}
		Offer model = offer.convertToModelObject();
		model.setGoods(goods);
		model.setService(service);
		
		offerDao.updateOffer(model);
		
	}

	@Override
	public OfferSO getModeratedOfferByOfferIdAndUserId(Long offerId, Long userId) {
		Offer model = offerDao.findModeratedOfferByOfferIdAndUserId(offerId, userId);
		if(model != null) {
			return model.convertToServiceObject();
		}
		return null;
	}
}
